﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Simhopp.Model;
using Simhopp.Presenter;
using System.Net;
using System.Net.Sockets;


namespace Simhopp.GUI
{
    //Listan av divers borde vara sorterad efter DiveNumber?!
    public partial class frmOngoingCompetition : Form, InterfaceOngoingCompetitionView
    {
        public event DelegateGetDiverList EventGetDiverList = null;
        public event DelegateGetDiveByDiveNumber EventGetDiveByDiveNumber = null;
        public event DelegateMoveDiverToBack EventMoveDiverToBack = null;
        public event DelegateAddScoreAndJudgeIDToJudgeScoreDict EventAddScoreAndJudgeIDToJudgeScoreDict = null;
        public event DelegateGetRound EventGetRound = null;
        
        public event DelegateGetJudgeScoreForDive EventGetJudgeScoreForDive = null;
        public event DelegateCalculateTotalScoreForDive EventCalculateTotalScoreForDive = null;
        public event DelegateCalculateTotalPointsForDiver EventCalculateTotalPointsForDiver = null;


        public event DelegateStart EventStart = null;
        public event DelegateStop EventStop = null;

        PresenterOngoingCompetition pOngoingCompetition;
        bool JudgesComplete;
        Competition currentComp;
        int PerformedDives = 0;
        public frmOngoingCompetition(Competition PropCompetition)
        {
            InitializeComponent();
            Listener listener = new Listener(888);
            listener.isJudge = false;
            currentComp = PropCompetition;
            currentComp.CompetingDivers = currentComp.DiverList.Count;
            currentComp.RoundsInCompetition = currentComp.DiverList[0].DiveList.Count;
            listener.SocketAccepted += new Listener.SocketAcceptedHandler(listener_SocketAccepted);
            pOngoingCompetition = new PresenterOngoingCompetition(this, currentComp,listener);
        }
        private void SetDiverOrderList()
        {
            if (EventGetDiverList != null)
            {
                lstvwDiverOrder.Items.Clear();

                foreach (Diver diver in EventGetDiverList())
                {
                    ListViewItem tempListView = new ListViewItem();
                    tempListView.Text = diver.StartNumber.ToString(); 
                    tempListView.SubItems.Add(diver.Name);
                    tempListView.Tag = diver;
                    lstvwDiverOrder.Items.Add(tempListView);
                }
            }
            lstvwDiverOrder.Items[0].Selected = true;
            foreach (ListViewItem item in lstvwDiverOrder.Items)
            {
                item.BackColor = item.Index % 2 == 0 ?
                    Color.Azure : Color.Snow;
            }
        }
        private void SetUpNextDiver()
        {
            txtDiverInfo.Clear(); txtDiveInfo.Clear();
            Diver diver = (Diver)lstvwDiverOrder.SelectedItems[0].Tag;
            pOngoingCompetition._modelDiver = diver;
            txtDiverInfo.Text = diver.Name;
            Dive dive = EventGetDiveByDiveNumber(Convert.ToInt32(txtRound.Text));
            txtDiveInfo.Text = dive.Name;
            txtDiver.Text = diver.StartNumber.ToString();
            btnNextDiver.Enabled = false;
            
            
        }
        private void frmOngoingCompetition_Load(object sender, EventArgs e)
        {
            if (EventStart != null && EventGetRound != null)
            {
                EventStart();
                txtRound.Text = EventGetRound().ToString();
            }
            SetDiverOrderList();
            JudgesComplete = false;
        }

        private void lstwDiverOrder_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstvwDiverOrder.SelectedItems.Count == 1)
            {
                pOngoingCompetition._modelDiver = (Diver)lstvwDiverOrder.SelectedItems[0].Tag;
            }
        }

        private void btnNextDiver_Click(object sender, EventArgs e)
        {
            if (EventMoveDiverToBack != null && lstvwDiverOrder.SelectedItems.Count == 1)
            {
                SetUpNextDiver();
                btnGetJudgePoints.Enabled = true;
                PerformedDives++;
            }
        }
        private void UpdateCurrentStanding()
        {
            if (EventGetDiverList != null)
            {
                List<Diver> DiverList = new List<Diver>();
                foreach (Diver diver in EventGetDiverList())
                {
                    DiverList.Add(diver);
                }
                DiverList.Sort((x, y) => y.TotalPoints.CompareTo(x.TotalPoints));
                lstvwCurrentStanding.Items.Clear();

                for (int i = 0; i < DiverList.Count; i++)
                {
                    int PerformedDives = 0;
                    int position = i + 1;
                    foreach (Dive dive in DiverList[i].DiveList)
                    {
                        if (dive.Score != 0)
                            PerformedDives++;
                    }
                    ListViewItem tempListView = new ListViewItem();
                    
                    tempListView.Text = position.ToString();
                    tempListView.SubItems.Add(DiverList[i].StartNumber.ToString());
                    tempListView.SubItems.Add(DiverList[i].Name);
                    tempListView.SubItems.Add(PerformedDives.ToString());
                    tempListView.SubItems.Add(DiverList[i].TotalPoints.ToString());
                    tempListView.Tag = DiverList[i];
                    lstvwCurrentStanding.Items.Add(tempListView);
                }


            }
            foreach (ListViewItem item in lstvwCurrentStanding.Items)
            {
                item.BackColor = item.Index % 2 == 0 ?
                    Color.Azure : Color.Snow;
            }
        }
        private void EmptyInformationAfterFinishedDive()
        {
            lstJudge1.Items.Clear(); lstJudge2.Items.Clear(); lstJudge3.Items.Clear(); lstJudge4.Items.Clear();
            lstJudge5.Items.Clear();
            txtTotalScore.Clear(); txtDiveInfo.Clear(); txtDiverInfo.Clear();
            txtDiver.Clear();
        }
        private void btnGetScores_Click(object sender, EventArgs e)
        {
            try
            {
                CheckIfJudgeScoringComplete();
                if (JudgesComplete)
                {
                    AddToDict();
                    EventCalculateTotalScoreForDive(Convert.ToInt32(txtRound.Text));
                    EventCalculateTotalPointsForDiver();
                    UpdateCurrentStanding();
                    EmptyInformationAfterFinishedDive();
                    EventMoveDiverToBack((Diver)lstvwDiverOrder.SelectedItems[0].Tag);
                    SetDiverOrderList();
                    if (PerformedDives % currentComp.CompetingDivers == 0)
                        currentComp.Round++;
                    btnGetScores.Enabled = false;
                    btnNextDiver.Enabled = true;
                    btnGetJudgePoints.Enabled = false;
                    JudgesComplete = false;
                    if (currentComp.RoundsInCompetition + 1 == currentComp.Round)
                    {       
                        lstvwCurrentStanding.Location = new Point(this.Width/4, 0);
                        HideControlsAfterFinished();                
                    }
                    else
                        txtRound.Text = currentComp.Round.ToString();
                }
            }
            catch (Exception ex) { MessageBox.Show("Wait for all judges to supply points" + ex.Message); }
        }
        private void HideControlsAfterFinished()
        {
            lstvwDiverOrder.Hide();
            lstvwConnectedJudges.Hide();
            lblConnectedJudges.Hide();
            lblCurrentStandings.Hide();
            lblDiveOrder.Hide();
            grpCurrentDiver.Hide();
            btnNextDiver.Hide();
            btnFinishEvent.Show();
        }
        private void AddToDict()
        {
            EventAddScoreAndJudgeIDToJudgeScoreDict(
                Convert.ToInt32(lstJudge1.ValueMember),
                Convert.ToInt32(txtRound.Text),
                Convert.ToDouble(lstJudge1.Items[0]));

            EventAddScoreAndJudgeIDToJudgeScoreDict(
                Convert.ToInt32(lstJudge2.ValueMember),
                Convert.ToInt32(txtRound.Text),
                Convert.ToDouble(lstJudge2.Items[0]));

            EventAddScoreAndJudgeIDToJudgeScoreDict(
                Convert.ToInt32(lstJudge3.ValueMember),
                Convert.ToInt32(txtRound.Text),
                Convert.ToDouble(lstJudge3.Items[0]));

            EventAddScoreAndJudgeIDToJudgeScoreDict(
                Convert.ToInt32(lstJudge4.ValueMember),
                Convert.ToInt32(txtRound.Text),
                Convert.ToDouble(lstJudge4.Items[0]));

            EventAddScoreAndJudgeIDToJudgeScoreDict(
                Convert.ToInt32(lstJudge5.ValueMember),
                Convert.ToInt32(txtRound.Text),
                Convert.ToDouble(lstJudge5.Items[0]));
            
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        void listener_SocketAccepted(System.Net.Sockets.Socket e)
        {
            Client client = new Client(e);
            client.Recived += new Client.ClientRecivedHandler(client_Recived);
            client.Disconnected += new Client.ClientDisconnectHandler(client_Disconnected);

            BeginInvoke((MethodInvoker)delegate
            {
                ListViewItem i = new ListViewItem();
                i.Text = client.EndPoint.ToString();
                i.SubItems.Add("--");
                i.SubItems.Add("--");
                i.SubItems.Add("--");
                i.SubItems.Add("--");
                i.Tag = client;
                lstvwConnectedJudges.Items.Add(i);

            });
            //foreach (ListViewItem item in lstvwConnectedJudges.Items)
            //{
            //    item.BackColor = item.Index % 2 == 0 ?
            //        Color.Azure : Color.Snow;
            //}

        }

        void client_Disconnected(Client sender)
        {
            try
            {
                BeginInvoke((MethodInvoker)delegate
                {
                    if (lstvwConnectedJudges.Items.Count == 0)
                    {
                        sender.Close();
                    }
                    for (int i = 0; i < lstvwConnectedJudges.Items.Count; i++)
                    {

                        Client client = lstvwConnectedJudges.Items[i].Tag as Client;

                        if (client.ID == sender.ID)
                        {
                            lstvwConnectedJudges.Items.RemoveAt(i);
                            break;

                        }
                    }

                });

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                
                
            }
            
        }

        void client_Recived(Client sender, byte[] data)
        {
            BeginInvoke((MethodInvoker)delegate
            {
                for (int i = 0; i < lstvwConnectedJudges.Items.Count; i++)
                {
                    Client client = lstvwConnectedJudges.Items[i].Tag as Client;

                    if (client.ID == sender.ID)
                    {
                        string[] recivedmsg = Encoding.Default.GetString(data).Split('@');//IP
                        if (recivedmsg[0] != "")
                        {
                            lstvwConnectedJudges.Items[i].SubItems[1].Text = recivedmsg[0];//JudgeID
                            lstvwConnectedJudges.Items[i].SubItems[2].Text = recivedmsg[1];//JudgeName
                            lstvwConnectedJudges.Items[i].SubItems[3].Text = recivedmsg[2];//Score
                            lstvwConnectedJudges.Items[i].SubItems[4].Text = recivedmsg[3];//PortNumber
                            if (i == 0)
                            {
                                lstJudge1.Items.Clear();
                                lstJudge1.Items.Add(lstvwConnectedJudges.Items[i].SubItems[3].Text);
                                lstJudge1.ValueMember = recivedmsg[0];
                            }
                            else if (i == 1)
                            {
                                lstJudge2.Items.Clear();
                                lstJudge2.Items.Add(lstvwConnectedJudges.Items[i].SubItems[3].Text);
                                lstJudge2.ValueMember = recivedmsg[0];
                            }
                            else if (i == 2)
                            {
                                lstJudge3.Items.Clear();
                                lstJudge3.Items.Add(lstvwConnectedJudges.Items[i].SubItems[3].Text);
                                lstJudge3.ValueMember = recivedmsg[0];
                            }
                            else if (i == 3)
                            {
                                lstJudge4.Items.Clear();
                                lstJudge4.Items.Add(lstvwConnectedJudges.Items[i].SubItems[3].Text);
                                lstJudge4.ValueMember = recivedmsg[0];
                            }
                            else if (i == 4)
                            {
                                lstJudge5.Items.Clear();
                                lstJudge5.Items.Add(lstvwConnectedJudges.Items[i].SubItems[3].Text);
                                lstJudge5.ValueMember = recivedmsg[0];
                            }
                        }
                        else
                        {
                            lstvwConnectedJudges.Items[i].SubItems[1].Text = null;//JudgeID
                            lstvwConnectedJudges.Items[i].SubItems[2].Text = null;//JudgeName
                            lstvwConnectedJudges.Items[i].SubItems[3].Text = null;//Score
                            lstvwConnectedJudges.Items[i].SubItems[4].Text = null;//PortNumber
                            
                        }

                        break;
                    }
                    
                }
                //foreach (ListViewItem item in lstvwConnectedJudges.Items)
                //{
                //    item.BackColor = item.Index % 2 == 0 ?
                //        Color.Azure : Color.Snow;
                //}

            });
        }
        private void CheckIfJudgeScoringComplete()
        {
            if (lstJudge1.Items[0].ToString() != "--" &&
                lstJudge2.Items[0].ToString() != "--" &&
                lstJudge3.Items[0].ToString() != "--" &&
                lstJudge4.Items[0].ToString() != "--" &&
                lstJudge5.Items[0].ToString() != "--")
            {
                JudgesComplete = true;
            }
            //lstJudge3.DisplayMember.ToString() != "--" &&
            //    lstJudge4.DisplayMember.ToString() != "--" &&
            //    lstJudge5.DisplayMember.ToString() != "--"
        }
        private void frmOngoingCompetition_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (EventStop != null)
                EventStop();
            
        }

        private void SentRequest()
        {
            for (int i = 0; i < lstvwConnectedJudges.Items.Count; i++)
            {
                Client client = lstvwConnectedJudges.Items[i].Tag as Client;
                
                Socket sck = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
                sck.Connect(client.EndPoint.Address,Convert.ToInt32(lstvwConnectedJudges.Items[i].SubItems[4].Text));
                string s = sck.LocalEndPoint.ToString() + '@' + txtDiverInfo.Text + "@" + txtDiveInfo.Text;
                sck.Send(Encoding.Default.GetBytes(s));
                sck.Close();
                sck.Dispose();
            }
        }

        private void btnGetJudgePoints_Click(object sender, EventArgs e)
        {
            if (lstvwConnectedJudges.Items.Count == 3)
            {
                SentRequest();
                FillJudgePointsLsb();
                btnGetScores.Enabled = true;
                //lstJudge3.Items.Clear();
                lstJudge4.Items.Clear();
                lstJudge5.Items.Clear();
                //lstJudge3.Items.Add("5");
                //lstJudge3.ValueMember = "3";
                lstJudge4.Items.Add("5");
                lstJudge4.ValueMember = "4";
                lstJudge5.Items.Add("5");
                lstJudge5.ValueMember = "5";
            }
            else
                MessageBox.Show("Waiting for " + (3 - lstvwConnectedJudges.Items.Count).ToString() + " judges");

            //lstJudge1.Items.Clear();
            //lstJudge2.Items.Clear();
            
            //lstJudge1.Items.Add("5");
            //lstJudge1.ValueMember = "1";
            //lstJudge2.Items.Add("5");
            //lstJudge2.ValueMember = "2";
            //lstJudge3.Items.Add("5");
            //lstJudge3.ValueMember = "3";
            //lstJudge4.Items.Add("5");
            //lstJudge4.ValueMember = "4";
            //lstJudge5.Items.Add("5");
            //lstJudge5.ValueMember = "5";
            //btnGetScores.Enabled = true;
        }
        private void FillJudgePointsLsb()
        {
            lstJudge1.Items.Clear(); lstJudge2.Items.Clear(); lstJudge3.Items.Clear();
            lstJudge4.Items.Clear(); lstJudge5.Items.Clear();

            lstJudge1.Items.Add("--"); lstJudge2.Items.Add("--"); lstJudge3.Items.Add("--");
            lstJudge4.Items.Add("--"); lstJudge5.Items.Add("--");
        }

        private void btnFinishEvent_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void lstvwCurrentStanding_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
    }

}
